package com.yupfeg.livedata

import androidx.annotation.MainThread
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import java.util.*
import java.util.concurrent.atomic.AtomicInteger

/**
 * 单次执行事件的LiveData
 * * 调用[observe]在指定生命周期作用内，订阅单次执行事件，单个订阅者在消费后，不会再次触发回调，
 * 一条事件能被多个观察者消费，而每一个消费者只能收到一次该事件，直到发送新事件
 * * 如果需要与生命周期不敏感的场景（如全局广播），可调用[observeForever]订阅，
 * 但在视图销毁时，需要手动调用[removeObserver]，防止内存泄漏
 *
 * @author yuPFeG
 * @date 2021/09/16
 */
open class EventLiveData<T> : LiveData<T>(){

    companion object{
        private const val DEF_VERSION = -1
    }

    protected val mEventVersion : AtomicInteger = AtomicInteger(DEF_VERSION)

    protected fun getNewestVersion() = mEventVersion.get()

    /**
     * 订阅单次执行事件变化，仅允许下游接收到非空值
     * * 简化外部kotlin调用
     * @param owner The LifecycleOwner which controls the observer
     * @param onValueChange 事件内容变化
     */
    @MainThread
    fun observe(owner: LifecycleOwner,onValueChange : (T)->Unit){
        observe(owner, Observer<T> {value->
            value?:return@Observer
            onValueChange.invoke(value)
        })
    }

    /**
     * 订阅单次执行事件变化，仅允许下游接收到非空值
     * @param owner The LifecycleOwner which controls the observer
     * @param observer  The observer that will receive the events
     */
    @MainThread
    override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
        val observerWrapper = SimpleObserverWrapper(getNewestVersion(),observer)
        super.observe(owner, observerWrapper)
    }

    /**
     * 订阅单次执行事件的LiveData，忽略视图生命周期变化
     * * 约等于广播，只要被订阅数据源变化，订阅者对象就会收到变化
     * */
    @MainThread
    override fun observeForever(observer: Observer<in T>) {
        val observerWrapper = SimpleObserverWrapper(getNewestVersion(),observer)
        super.observeForever(observerWrapper)
    }

    /**
     * 移除订阅对象
     * * 通常仅用于[observeForever]的订阅对象，由于没有关联生命周期，所以需要手动移除该对象，避免内存移除
     * @param observer
     */
    @MainThread
    override fun removeObserver(observer: Observer<in T>) {
        val wrapper = SimpleObserverWrapper(DEF_VERSION,observer)
        super.removeObserver(wrapper)
    }

    /**
     * 所有的赋值操作最终都会调用该方法
     * @param value
     */
    override fun setValue(value: T?) {
        //将内部维护的版本号+1
        mEventVersion.getAndIncrement()
        super.setValue(value)
    }

    /**
     * 内部类，liveData订阅的包装类
     * * 内部维护版本号，确定该订阅对象是否已消费
     * */
    protected open inner class SimpleObserverWrapper(
        private var mLastVersion: Int,
        private val mObserver: Observer<in T>,
    ) : Observer<T>{

        /**
         * Called when the data is changed.
         * @param t  The new data
         */
        override fun onChanged(t: T) {
            val newVersion = getNewestVersion()
            if (mLastVersion >= newVersion) return

            //数据发送变化，更新版本号
            mLastVersion = newVersion
            mObserver.onChanged(t)
        }

        override fun equals(other: Any?): Boolean {
            if (this === other) {
                return true
            }
            if (other == null || javaClass != other.javaClass) {
                return false
            }
            val that = other as? EventLiveData<*>.SimpleObserverWrapper
            return mObserver == that?.mObserver
        }

        override fun hashCode(): Int {
            return Objects.hash(mObserver)
        }
    }
}